package jinyilw.common.math;

public class Complex
{
	private final double real;
	private final double imaginary;

	public Complex(double r, double i)
	{
		real = r;
		imaginary = i;
	}

	public double real()
	{
		return real;
	}

	public double imaginary()
	{
		return imaginary;
	}

	public double modulus()
	{
		return Math.sqrt(real * real + imaginary * imaginary);
	}

	public boolean equal(Complex paramComplex)
	{
		return ((real == paramComplex.real)
				&& (imaginary == paramComplex.imaginary));
	}

	public Complex add(Complex paramComplex)
	{
		return new Complex(real + paramComplex.real,
				imaginary + paramComplex.imaginary);
	}

	public Complex subtract(Complex paramComplex)
	{
		return new Complex(real - paramComplex.real,
				imaginary - paramComplex.imaginary);
	}

	public Complex multiply(Complex paramComplex)
	{
		return new Complex(
				real * paramComplex.real - (imaginary * paramComplex.imaginary),
				real * paramComplex.imaginary + imaginary * paramComplex.real);
	}

	public Complex divide(Complex paramComplex)
	{
		double f1 = paramComplex.real * paramComplex.real
				+ paramComplex.imaginary * paramComplex.imaginary;
		double f2 = (real * paramComplex.real
				+ imaginary * paramComplex.imaginary) / f1;
		double f3 = (imaginary * paramComplex.real
				- (real * paramComplex.imaginary)) / f1;

		return new Complex(f2, f3);
	}

	@Override
	public String toString()
	{
		String str = (this.imaginary >= 0.0F) ? "+" : "-";
		return this.real + str + Math.abs(this.imaginary) + "i";
	}

	// 复数平方
	public static double[] sqr(double[] c)
	{
		double x = c[0], y = c[1];
		return new double[]{x * x - y * y, 2 * x * y};
	}

	// 复数乘法
	public static double[] mul(double[] c0, double[] c1)
	{
		double x0 = c0[0], y0 = c0[1];
		double x1 = c1[0], y1 = c1[1];
		return new double[]{x0 * x1 - y0 * y1, x0 * y1 + x1 * y0};
	}

	// 复数的N次方！！！
	public static double[] pow(double[] c, int N)
	{
		double x = c[0], y = c[1];
		double out_x, out_y;
		switch (N)
		{
			case 0:
			{
				out_x = 1;
				out_y = 0;
			}
			break;
			case 1:
			{
				out_x = x;
				out_y = y;
			}
			break;
			case 2:
			{
				return sqr(c);
			}
			case 3:
			{
				double[] o = sqr(c);
				return mul(c, o);
			}
			case 4:
			{
				double[] o = sqr(c);
				return sqr(o);
			}
			case 5:
			{
				double[] o = sqr(c);
				double[] o2 = sqr(o);
				return mul(c, o2);
			}
			case 6:
			{
				double[] o = sqr(c);
				double[] o2 = sqr(o);
				return mul(o, o2);
			}
			default:
			{
				int half = N >> 1;
				double[] po = pow(c, half);
				if ((N & 1) == 0)
					return sqr(po);
				else
				{
					double[] sq = sqr(po);
					return mul(c, sq);
				}
			}
		}
		return new double[]{out_x, out_y};
	}

	// 显然是复数除法运算
	public static double[] div(double[] c0, double[] c1)
	{
		double x0 = c0[0], y0 = c0[1];
		double x1 = c1[0], y1 = c1[1];
		double r = 1 / (x1 * x1 + y1 * y1 + 1e-300);
		double out_x = (x0 * x1 + y0 * y1) * r;
		double out_y = (y0 * x1 - x0 * y1) * r;
		return new double[]{out_x, out_y};
	}

	public static boolean equal(double[] c0, double[] c1)
	{
		double x0 = c0[0], y0 = c0[1];
		double x1 = c1[0], y1 = c1[1];
		return ((x0 == x1) && (y0 == y1));
	}

	public static double[] add(double[] c0, double[] c1)
	{
		double x0 = c0[0], y0 = c0[1];
		double x1 = c1[0], y1 = c1[1];
		return new double[]{x0 + x1, y0 + y1};
	}

	public static double[] sub(double[] c0, double[] c1)
	{
		double x0 = c0[0], y0 = c0[1];
		double x1 = c1[0], y1 = c1[1];
		return new double[]{x0 - x1, y0 - y1};
	}
}
